From: Giovanni Campagna Date: Thu, 6 Sep 2012 14:40:13 +0000 (+0200) Subject: ShellUserVerifier: catch DBus errors and report them to the user X-Git-Tag: archive/raspbian/50.5-1+rpi1~1^2~1013^2^2~5813 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=10884ef7f5ba0b5a0ad96130b4e386af813819af;p=gnome-shell.git ShellUserVerifier: catch DBus errors and report them to the user Instead of leaving the login or unlock dialogs in an inconsistent state, catch DBus errors and show an Authentication Error message. The error details are logged in the session logs. https://bugzilla.gnome.org/show_bug.cgi?id=683060 --- diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js index 3d7996c4f..8cb439581 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -649,6 +649,10 @@ const LoginDialog = new Lang.Class({ this._userVerifier.connect('ask-question', Lang.bind(this, this._askQuestion)); this._userVerifier.connect('show-message', Lang.bind(this, this._showMessage)); this._userVerifier.connect('reset', Lang.bind(this, this._onReset)); + this._userVerifier.connect('not-supported', Lang.bind(this, function(verifier, error) { + Main.notifyError(_("Configuration problem: Could not connect to GDM"), error.message); + this._onReset(); + })); this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint)); this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint)); diff --git a/js/gdm/util.js b/js/gdm/util.js index 681c0a69b..4d4754d6d 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -141,34 +141,43 @@ const ShellUserVerifier = new Lang.Class({ })); }, + _reportInitError: function(where, error) { + logError(error, where); + this._hold.relase(); + + this.emit('show-message', _("Authentication error"), 'login-dialog-message-warning'); + this._verificationFailed(false); + }, + _reauthenticationChannelOpened: function(client, result) { try { this._userVerifier = client.open_reauthentication_channel_finish(result); - this._connectSignals(); - this._beginVerification(); - - this._hold.release(); - } catch (e) { - if (this._reauthOnly) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - return; - - logError(e, 'Failed to open reauthentication channel'); - this.emit('verification-failed'); - this._hold.release(); - return; - } - - // If there's no session running, or it otherwise fails, then fall back - // to performing verification from this login session + } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { + return; + } catch(e if e.matches(Gio.DBusError, Gio.DBusError.ACCESS_DENIED) && + !this._reauthOnly) { + // Gdm emits org.freedesktop.DBus.Error.AccessDenied when there is + // no session to reauthenticate. Fall back to performing verification + // from this login session client.get_user_verifier(this._cancellable, Lang.bind(this, this._userVerifierGot)); + return; + } catch(e) { + this._reportInitError('Failed to open reauthentication channel', e); + return; } + + this._connectSignals(); + this._beginVerification(); + this._hold.release(); }, _userVerifierGot: function(client, result) { try { this._userVerifier = client.get_user_verifier_finish(result); - } catch(e if e.matches(Gio.IOErrorEnum, Gio.ErrorEnum.CANCELLED)) { + } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { + return; + } catch(e) { + this._reportInitError('Failed to obtain user verifier', e); return; } @@ -199,6 +208,9 @@ const ShellUserVerifier = new Lang.Class({ obj.call_begin_verification_for_user_finish(result); } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { return; + } catch(e) { + this._reportInitError('Failed to start verification for user', e); + return; } this._hold.release(); @@ -215,6 +227,9 @@ const ShellUserVerifier = new Lang.Class({ obj.call_begin_verification_for_user_finish(result); } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { return; + } catch(e) { + this._reportInitError('Failed to start fingerprint verification for user', e); + return; } this._hold.release(); @@ -228,6 +243,9 @@ const ShellUserVerifier = new Lang.Class({ obj.call_begin_verification_finish(result); } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { return; + } catch(e) { + this._reportInitError('Failed to start verification', e); + return; } this._hold.release(); @@ -306,23 +324,27 @@ const ShellUserVerifier = new Lang.Class({ this.emit('verification-complete'); }, - _verificationFailed: function() { + _verificationFailed: function(retry) { // For Not Listed / enterprise logins, immediately reset // the dialog // Otherwise, we allow ALLOWED_FAILURES attempts. After that, we // go back to the welcome screen. - if (!this._userName || - (++this._failCounter) == this._settings.get_int(ALLOWED_FAILURES_KEY)) { + let canRetry = retry && this._userName && + this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY); + + if (canRetry) { + this._failCounter++; + + this.clear(); + this.begin(this._userName, new Batch.Hold()); + } else { // Allow some time to see the message, then reset everything Mainloop.timeout_add(3000, Lang.bind(this, function() { this.cancel(); this._onReset(); })); - } else { - this.clear(); - this.begin(this._userName, new Batch.Hold()); } this.emit('verification-failed'); @@ -333,7 +355,7 @@ const ShellUserVerifier = new Lang.Class({ // But if, e.g., fingerprint fails, still give // password authentication a chance to succeed if (serviceName == PASSWORD_SERVICE_NAME) { - this._verificationFailed(); + this._verificationFailed(true); } this.emit('hide-login-hint'); diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js index 127a924c7..8701a430d 100644 --- a/js/ui/unlockDialog.js +++ b/js/ui/unlockDialog.js @@ -133,6 +133,12 @@ const UnlockDialog = new Lang.Class({ this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint)); this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint)); + this._userVerifier.connect('not-supported', Lang.bind(this, function(verifier, error) { + Main.notifyError(_("Could not connect to GDM. Screen locking was automatically disabled."), error.message); + this._userVerifier.clear(); + this.emit('unlocked'); + })); + this._userWidget = new UserWidget(this._user); this.contentLayout.add_actor(this._userWidget.actor);